#pragma once

#include<iostream>
#include<string>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<strings.h>
#include<cstdlib>
#include<functional>
#include"InetAddr.hpp"
#include"Logger.hpp"

using callback_t = std::function<void\
 (int sockfd , std::string message , InetAddr addr)>;
 
static const int gdefaultsockfd = -1;

class ChatServer
{
public:
    //构造
    ChatServer(uint16_t port , callback_t cb)
        :_port(port)
        ,_sockfd(gdefaultsockfd)
        ,_isrunning(false)
        ,_cb(cb)
    {}

    //初始化
    void Init()
    {
        //创建套接字
        //基于网络 数据报的套接字
        _sockfd = socket(AF_INET , SOCK_DGRAM, 0);
        //创建套接字失败
        if(_sockfd < 0)
        {
            LOG(LogLevel::FATAL) << "create socket error";
            exit(1);
        }
        LOG(LogLevel::INFO) << "create socket success: " << _sockfd;

        //网络风格的地址
        InetAddr local(_port);//传端口过去
        //将local 与 套接字进行bind
        int n = bind(_sockfd , local.Addr() , local.Length());
        if(n < 0)
        {
            //bind 失败
            LOG(LogLevel::FATAL) << "bind sockfe error";
            exit(2);
        }
        LOG(LogLevel::INFO) << "bind sockfd success: " << _sockfd; 
    }

    //开始
    void Start()
    {
        //所有的服务器均是死循环
        _isrunning = true;
        while(_isrunning)
        {
            char buffer[1024];
            buffer[0] = 0;//清空缓冲区
            struct sockaddr_in peer;
            socklen_t len = sizeof(peer);
            //从网络中读取数据
            ssize_t n = recvfrom(_sockfd , buffer , sizeof(buffer) , 0 , (struct sockaddr*)&peer , &len);
            if(n>0)
            {
                //读取成功
                buffer[n] = 0;
                InetAddr clientaddr(peer);//peer 就是客户端的地址
                LOG(LogLevel::DEBUG) << "get a client info # " << clientaddr.Ip() << "-"
                <<clientaddr.Port() <<":" <<buffer;

                std::string message = buffer;
                //回调
                _cb(_sockfd , message , clientaddr);
            }
        }
        _isrunning = false;
    }
    //停止
    void Stop()
    {
        _isrunning = false;
    }
    //析构
    ~ChatServer(){}
private:
    int _sockfd;//套接字
    uint16_t _port;//对于服务器来说不要指定ip，给port 就可以了
    callback_t _cb;//回调函数
    bool _isrunning;
};